package com.moyoutian.leetcode;

/**
 * 437. 路径总和 III
 * <p>
 * 给定一个二叉树的根节点 root ，和一个整数 targetSum ，求该二叉树里节点值之和等于 targetSum 的 路径 的数目。
 * <p>
 * 路径 不需要从根节点开始，也不需要在叶子节点结束，但是路径方向必须是向下的（只能从父节点到子节点）。
 * <p>
 * <p>
 * <p>
 * 示例 1：
 * <p>
 * 输入：root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
 * 输出：3
 * 解释：和等于 8 的路径有 3 条，如图所示。
 * <p>
 * 示例 2：
 * <p>
 * 输入：root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
 * 输出：3
 * <p>
 * <p>
 * <p>
 * 提示:
 * <p>
 * 二叉树的节点个数的范围是 [0,1000]
 * -109 <= Node.val <= 109
 * -1000 <= targetSum <= 1000
 */
public class Demo437 {

    public static class TreeNode {
        int val;
        TreeNode left;
        TreeNode right;

        TreeNode() {
        }

        TreeNode(int val) {
            this.val = val;
        }

        TreeNode(int val, TreeNode left, TreeNode right) {
            this.val = val;
            this.left = left;
            this.right = right;
        }
    }

    public static void main(String[] args) {
        //demo1 root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
        //          10
        //         /  \
        //        5    -3
        //       / \     \
        //      3   2    11
        //     / \   \
        //    3  -2   1
        TreeNode head = new TreeNode(10);
        head.left = new TreeNode(5);
        head.right = new TreeNode(-3);
        head.left.left = new TreeNode(3);
        head.left.right = new TreeNode(2);
        head.right.left = null;
        head.right.right = new TreeNode(11);
        head.left.left.left = new TreeNode(3);
        head.left.left.right = new TreeNode(-2);
        head.left.right.left = null;
        head.left.right.right = new TreeNode(1);


        //demo2 root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
        //          5
        //         /  \
        //        4     8
        //       /     / \
        //     11     13  4
        //     / \       / \
        //    7   2     5   1
        TreeNode head2 = new TreeNode(5);

        head2.left = new TreeNode(4);
        head2.left.left = new TreeNode(11);
        head2.left.left.left = new TreeNode(7);
        head2.left.left.right = new TreeNode(2);

        head2.right = new TreeNode(8);
        head2.right.left = new TreeNode(13);
        head2.right.right = new TreeNode(4);
        head2.right.right.left = new TreeNode(5);
        head2.right.right.right = new TreeNode(1);

        System.out.println(pathSum(head2, 22));
    }


    /**
     * 求该二叉树里节点值之和等于 targetSum 的 路径 的数目。
     *
     * @param root      根节点
     * @param targetSum 目标数
     * @return 路径数
     */
    public static int pathSum(TreeNode root, int targetSum) {
        if (root == null) {
            return 0;
        }

        return pathSum(root.left, targetSum) + pathSum(root.right, targetSum);
    }

    /**
     * 求该二叉树里节点值之和等于 targetSum 的 路径 的数目。
     *
     * @param root      根节点
     * @param targetSum 目标数
     * @return 路径数
     */
    public static int pathSum1(TreeNode root, int targetSum) {
        if (root == null) {
            return 0;
        }
        int count = sumNode(root, targetSum);
        if (root.left != null) {
            count += pathSum1(root.left, targetSum);
        }
        if (root.right != null) {
            count += pathSum1(root.right, targetSum);
        }
        return count;
    }

    public static int sumNode(TreeNode node, int targetSum) {
        int count = 0;
        if (node.left != null) {
            count += sumNode(node.left, targetSum - node.val);
        }
        if (node.right != null) {
            count += sumNode(node.right, targetSum - node.val);
        }
        if (node.val == targetSum) {
            count += 1;
        }
        return count;
    }
}
